package com.hsnn.medstgmini.trading.pur.dao.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.hsnn.medstgmini.base.std.dao.StdCompinfoDao;
import com.hsnn.medstgmini.base.std.dao.StdHospInfoDao;
import com.hsnn.medstgmini.base.std.model.HospInfo;
import com.hsnn.medstgmini.base.std.model.StdCompinfo;
import com.hsnn.medstgmini.exception.MSException;
import com.hsnn.medstgmini.pro.base.dao.BaseGoodsDao;
import com.hsnn.medstgmini.sys.model.SysUser;
import com.hsnn.medstgmini.trading.pur.dao.AddressDao;
import com.hsnn.medstgmini.trading.pur.dao.CreateOrderDao;
import com.hsnn.medstgmini.trading.pur.dao.PurOrderInfoDao;
import com.hsnn.medstgmini.trading.pur.model.HospAddress;
import com.hsnn.medstgmini.trading.pur.model.OrderPackStatus;
import com.hsnn.medstgmini.trading.pur.model.PurConfig;
import com.hsnn.medstgmini.trading.pur.model.PurPurPlan;
import com.hsnn.medstgmini.trading.pur.model.form.CreateOrderForm;
import com.hsnn.medstgmini.trading.pur.model.form.PurPlanForm;
import com.hsnn.medstgmini.util.DateUtil;

/**
 * @category 医疗机构生成订单
 * @author 蔡春龙
 * @date 2015年7月8日
 */
@Repository
public class CreateOrderDaoImpl implements CreateOrderDao {
	private final static Logger log = Logger.getLogger(CreateOrderDaoImpl.class);
	@Autowired
	private StdHospInfoDao stdHospInfoDao;
	
	@Autowired
	private AddressDao addressDao;
	
	@Autowired
	private StdCompinfoDao stdCompinfoDao;
	
	@Autowired
	private BaseGoodsDao baseGoodsDao; 
	
	@Autowired
	private PurOrderInfoDao purOrderInfoDao;
	
	@Resource(name = "sessionFactory")
	private SessionFactory factory;

	/**
	 * @category 提交订单
	 * @date 2015年7月10日
	 * @param orderForm
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public void submitOrder(CreateOrderForm orderForm, SysUser user) {
		Session session = factory.getCurrentSession();
		if (orderForm != null) {
				// 待生成订单的购物计划
				List<PurPlanForm> planList = orderForm.getPlanList();
				
				// 查询实际尚未生成订单的购物计划
				List<String> planIdList = new LinkedList<String>();
				for (PurPlanForm plan : planList) {
					planIdList.add(plan.getCartId());
				}
				Criteria criteria = session.createCriteria(PurPurPlan.class);
				criteria.add(Restrictions.in("cartId", planIdList));
				List<PurPurPlan> list = criteria.list(); // 实际尚未生成订单的购物计划

				if (list == null || list.isEmpty()) {
					throw new MSException(MSException.ALL_PLAN_ALREADY_TO_ORDER, "购物计划已提交，请勿重复提交！");
				} else if (orderForm.getConfirm() == 0 && list.size() != planList.size()) {
					throw new MSException(MSException.SOME_PLAN_ALREADY_TO_ORDER, "部分购物计划已提交，确定提交剩余购物计划吗？");
				}
				
				Criteria configCriteria = session.createCriteria(PurConfig.class);//获取采购设置信息
				List<PurConfig> configList = configCriteria.list();
				if (planList != null && !planList.isEmpty()) {
					Map<String, String> configMap = configListToMap(configList);//获取采购设置id与值的键值对
					
					int confirmDay = 0; // 企业确认截止天数
					int dispatchDay = 0; // 企业配送截止天数
					String confirmDayStr = "";
					String dispatchDayStr = "";
					if(StringUtils.isNotBlank(configMap.get("999432a1-23d0-11e5-9cc0-40f2e9d2c708"))){
						confirmDayStr = configMap.get("999432a1-23d0-11e5-9cc0-40f2e9d2c708");//订单提交后最迟确认时间
					}
					if(StringUtils.isNotBlank(configMap.get("999821f9-23d0-11e5-9cc0-40f2e9d2c708"))){
						dispatchDayStr = configMap.get("999821f9-23d0-11e5-9cc0-40f2e9d2c708");//订单确认后后最迟配送时间
					}
					
					if (StringUtils.isNotBlank(confirmDayStr)) {
						try {
							confirmDay = Integer.parseInt(confirmDayStr, 10);
						} catch (NumberFormatException e) {
							log.error("confirmDay is not integer, ", e);					}
					}
					if (StringUtils.isNotBlank(dispatchDayStr)) {
						try {
							dispatchDay = Integer.parseInt(dispatchDayStr, 10);
						} catch (NumberFormatException e) {
							log.error("dispatchDay is not integer, ", e);		
						}
					}

					// 生成订单对象
					if (!list.isEmpty()) {
						/*
						 * 统计条目数
						 */
						HospInfo hospInfo = user.getInfo();
						HospAddress hospAddress = new HospAddress();
						if(StringUtils.isNotBlank(orderForm.getRecpAddrId())){
							 hospAddress =	addressDao.getAddressById(orderForm.getRecpAddrId());
						}
						Map<String,Integer> delCodeAndCountMap = new HashMap<String, Integer>();//key 配送企业编码 value 条目数 
						Map<String, BigDecimal> priceMap = new HashMap<String, BigDecimal>();//key 配送企业编码 value 采购总金额
						for(int j=0;j<list.size();j++){
							PurPurPlan plan = list.get(j);
							for(int m = 0;m<planList.size();m++){
								if(plan.getCartId().equals(planList.get(m).getCartId())){
									plan.setProCount(Integer.valueOf(planList.get(m).getBuyNum()));
								}
							}
							Integer delresult = delCodeAndCountMap.get(plan.getDelCompCode());
							if(null == delresult){
								Integer goodscount = 1;
								delCodeAndCountMap.put(plan.getDelCompCode(), goodscount);
								BigDecimal firstCount = new BigDecimal(plan.getProCount());//初始采购数量
								BigDecimal firstPrice = new BigDecimal(plan.getProPrice());//初始采购价
								priceMap.put(plan.getDelCompCode(), firstCount.multiply(firstPrice));
							}else{
							 Integer oldgoodscount = delCodeAndCountMap.get(plan.getDelCompCode());
							 oldgoodscount += 1;
							 delCodeAndCountMap.put(plan.getDelCompCode(), oldgoodscount);
							 BigDecimal nextCount = new BigDecimal(plan.getProCount());//下一个商品采购数量
							 BigDecimal nextPrice = new BigDecimal(plan.getProPrice());//下一个商品采购价
							 BigDecimal nextAllPrice = nextCount.multiply(nextPrice);
							 priceMap.put(plan.getDelCompCode(),nextAllPrice.add(priceMap.get(plan.getDelCompCode())));
							}
						}
						
						Integer codeIndex = 0;
						Integer packIndex = 0;
						String prefix = getNum();
						Map<String, String> packIndexMap = new HashMap<String, String>();// 配送企业-订单包号
						Map<String, Integer> codeMap = new HashMap<String, Integer>();//key 订单包号后面序号  value 订单明细号后面序号
						for (int i=0;i<list.size();i++) {
							PurPurPlan plan = list.get(i);
							String packIndexStr = packIndexMap.get(plan.getDelCompCode());
							if (StringUtils.isBlank(packIndexStr)) {
								packIndex++;
								codeIndex++;
								packIndexStr = fillZero(packIndex, 3);//订单编号
								packIndexMap.put(plan.getDelCompCode(), packIndexStr);
								codeMap.put(packIndexStr, codeIndex);//
								
								// 保存订单
								StringBuffer hql = new StringBuffer();
								hql.append(" insert into pur_orderpack(order_pack_id,hosp_code,hosp_name,hosp_spel_code,hosp_status, ");
								hql.append(" hosp_area_id,hosp_area_name,hosp_ar_shortname,hosp_ar_fullname,user_id,recp_addr_id,recp_addr_s,");
								hql.append(" recp_addr,recp_user,recp_userphone,order_beg_time,order_end_time,count,amount,remarks, ");
								hql.append(" submit_datetime,submit_user,del_comp_code,del_comp_name,del_comp_name_spel,del_comp_status, ");
								hql.append(" order_status, ");
								hql.append(" order_conf_end_time,order_del_end_time,is_urgent) ");
								hql.append(" values(:order_pack_id , :hosp_code , :hosp_name , :hosp_spel_code , :hosp_status , :hosp_area_id ,  ");
								hql.append(" :hosp_area_name , :hosp_ar_shortname , :hosp_ar_fullname , :user_id , :recp_addr_id , :recp_addr_s , ");
								hql.append(" :recp_addr , :recp_user , :recp_userphone , :order_beg_time , :order_end_time , :count , :amount , ");
								hql.append(" :remarks , :submit_datetime , :submit_user , :del_comp_code , :del_comp_name , :del_comp_name_spel , ");
								hql.append(" :del_comp_status , ");
								hql.append(" :order_status , :order_conf_end_time , :order_del_end_time , :is_urgent) ");
								SQLQuery query = session.createSQLQuery(hql.toString());
								
								query.setString("order_pack_id",prefix + packIndexStr);//订单包号
								
								query.setString("hosp_code",plan.getHospCode() );//采购医疗机构编码
								query.setString("hosp_name",hospInfo.getHospName() );
								query.setString("hosp_spel_code",hospInfo.getHospSpelCode() );
								query.setInteger("hosp_status",hospInfo.getStatus() );
								query.setString("hosp_area_id",hospInfo.getArea().getAreaid() );
								query.setString("hosp_area_name",hospInfo.getArea().getAreaname() );
								query.setString("hosp_ar_shortname",hospInfo.getArea().getArshortname() );
								query.setString("hosp_ar_fullname",hospInfo.getArea().getArfullname() );
								query.setString("user_id",user.getId() );//采购用户
								query.setString("recp_addr_id",orderForm.getRecpAddrId() );
								query.setString("recp_addr_s",hospAddress.getRecpAddrS() );
								query.setString("recp_addr",hospAddress.getRecpAddr() );
								query.setString("recp_user",hospAddress.getRecpUser() );
								query.setString("recp_userphone",hospAddress.getRecpUserphone() );
								query.setTimestamp("order_beg_time",orderForm.getStartTime() );
								query.setTimestamp("order_end_time",orderForm.getEndTime() );
								query.setInteger("count",delCodeAndCountMap.get(plan.getDelCompCode()));//总条目数
								query.setBigDecimal("amount",priceMap.get(plan.getDelCompCode()) );//总金额
								query.setString("remarks",orderForm.getRemark() );
								query.setTimestamp("submit_datetime",new Date());
								query.setString("submit_user",user.getId() );
								if(StringUtils.isNotBlank(plan.getDelCompCode())){
									StdCompinfo compInfo = stdCompinfoDao.getCompInfoByCode(plan.getDelCompCode());
									query.setString("del_comp_code",plan.getDelCompCode() );
									query.setString("del_comp_name",compInfo.getCompName() );
									query.setString("del_comp_name_spel",compInfo.getCompSpelCode() );
									query.setInteger("del_comp_status",Integer.valueOf(compInfo.getStatus().toString()) );
								}
								query.setInteger("order_status",OrderPackStatus.submit.getKey() );
								if(confirmDay != 0){
									query.setTimestamp("order_conf_end_time",DateUtil.getTimeStamp(confirmDay) );//订单确认截止时间
								}else{
									query.setTimestamp("order_conf_end_time",null);//订单确认截止时间
								}
								if(dispatchDay != 0){
									query.setTimestamp("order_del_end_time",DateUtil.getTimeStamp(dispatchDay) );//订单配送截止时间
								}else{
									query.setTimestamp("order_del_end_time",null );//订单配送截止时间
								}
								query.setInteger("is_urgent",orderForm.getIsUrgent() );//是否是急救药品订单
								query.executeUpdate();
								session.flush();
								session.clear();
							}else{
								Integer result = codeMap.get(packIndexStr);
								result ++ ;
								codeMap.put(packIndexStr,result);
							}
							
							PurPurPlan planOrder = list.get(i);
							String orderPackId = prefix +packIndexMap.get(planOrder.getDelCompCode());
							codeIndex  = codeMap.get(packIndexMap.get(planOrder.getDelCompCode()));
							String codeIndexStr = fillZero(codeIndex, 5);
							//商品编码不为空将商品信息保存到订单明细表中
							if(StringUtils.isNotBlank(planOrder.getGoodsCode())){
								Map<String,Object> map = baseGoodsDao.getGoodsByCode(planOrder.getGoodsCode());
								map.put("order_code", orderPackId+codeIndexStr);
								map.put("order_pack_id", orderPackId);
								for(int n=0;n<planList.size();n++){
									if(planList.get(n).getCartId().equals(planOrder.getCartId())){
										map.put("pro_count", planList.get(n).getBuyNum());
									}
								}
								map.put("del_count", "0");
								map.put("pro_price", planOrder.getProPrice());
								map.put("join_plan_time", planOrder.getJoinPlanTime());
								map.put("join_plan_user", planOrder.getJoinPlanUser());
								map.put("order_status", OrderPackStatus.submit.getKey());
								map.put("confirm_remark", "");
								purOrderInfoDao.saveOrderDetail(map);
								// 从购物计划中删除
								session.delete(planOrder);
								session.flush();
							}
						}
						session.flush();
					}

				 }
				}
			}

	/**
	 * @category 生成编号
	 * @date 2015年7月10日
	 * @return
	 */
	private String getNum() {
		String str = "";
		Date date = new Date();
		SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
		str = format.format(date) + getRandom();
		return str;
	}

	/**
	 * @category 生成5位随机数不足补零
	 * @date 2015年7月10日
	 * @return
	 */
	private String getRandom() {
		int random = (int) Math.floor(Math.random() * 10000);
		return fillZero(random, 4);
	}

	/**
	 * @category 补零
	 * @return
	 */
	private String fillZero(int number, int length) {
		String f = "%0" + length + "d";
		return String.format(f, number);
	}

	/**
	 * @category list转map
	 * @date 2015年7月13日
	 * @param configList
	 * @return
	 */
	private Map<String, String> configListToMap(List<PurConfig> configList) {
		Map<String, String> map = new HashMap<String, String>();
		if (configList != null && !configList.isEmpty()) {
			for (PurConfig config : configList) {
				map.put(config.getConfigId(), config.getConfigValue());
			}
		}
		return map;
	}

}
